package com.blog.cmrpersonalblog.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blog.cmrpersonalblog.dto.notification.requset.NotificationQueryRequest;
import com.blog.cmrpersonalblog.dto.notification.respnose.NotificationGroupResponse;
import com.blog.cmrpersonalblog.dto.notification.respnose.NotificationResponse;
import com.blog.cmrpersonalblog.entity.Notification;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * 通知Mapper接口
 */
public interface NotificationMapper extends BaseMapper<Notification> {

    /**
     * 分页查询通知列表
     * @param page 分页对象
     * @param userId 用户ID
     * @param query 查询条件
     * @return 通知分页列表
     */
    IPage<NotificationResponse> selectNotificationPage(Page<NotificationResponse> page,
                                                       @Param("userId") Long userId,
                                                       @Param("query") NotificationQueryRequest query);

    /**
     * 获取通知详情
     * @param notificationId 通知ID
     * @param userId 用户ID
     * @return 通知详情
     */
    NotificationResponse selectNotificationDetail(@Param("notificationId") Long notificationId,
                                                   @Param("userId") Long userId);

    /**
     * 获取用户未读通知数量
     * @param userId 用户ID
     * @return 未读数量
     */
    Integer countUnreadNotifications(@Param("userId") Long userId);

    /**
     * 获取用户指定类型的未读通知数量
     * @param userId 用户ID
     * @param type 通知类型
     * @return 未读数量
     */
    Integer countUnreadNotificationsByType(@Param("userId") Long userId, @Param("type") String type);

    /**
     * 标记通知为已读
     * @param notificationId 通知ID
     * @param userId 用户ID
     * @return 影响行数
     */
    int markAsRead(@Param("notificationId") Long notificationId, @Param("userId") Long userId);

    /**
     * 批量标记通知为已读
     * @param notificationIds 通知ID列表
     * @param userId 用户ID
     * @return 影响行数
     */
    int batchMarkAsRead(@Param("notificationIds") List<Long> notificationIds, @Param("userId") Long userId);

    /**
     * 标记所有通知为已读
     * @param userId 用户ID
     * @param type 通知类型（可选）
     * @return 影响行数
     */
    int markAllAsRead(@Param("userId") Long userId, @Param("type") String type);

    /**
     * 删除通知
     * @param notificationId 通知ID
     * @param userId 用户ID
     * @return 影响行数
     */
    int deleteNotification(@Param("notificationId") Long notificationId, @Param("userId") Long userId);

    /**
     * 批量删除通知
     * @param notificationIds 通知ID列表
     * @param userId 用户ID
     * @return 影响行数
     */
    int batchDeleteNotifications(@Param("notificationIds") List<Long> notificationIds, @Param("userId") Long userId);

    /**
     * 清空已读通知
     * @param userId 用户ID
     * @return 影响行数
     */
    int clearReadNotifications(@Param("userId") Long userId);

    /**
     * 获取最新通知列表
     * @param userId 用户ID
     * @param limit 限制数量
     * @return 通知列表
     */
    List<NotificationResponse> selectLatestNotifications(@Param("userId") Long userId, @Param("limit") Integer limit);

    /**
     * 检查是否存在相同的通知（防止重复通知）
     * @param userId 用户ID
     * @param senderId 发送者ID
     * @param type 通知类型
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @param minutes 时间范围（分钟）
     * @return 是否存在
     */
    Boolean existsSimilarNotification(@Param("userId") Long userId,
                                      @Param("senderId") Long senderId,
                                      @Param("type") String type,
                                      @Param("targetType") String targetType,
                                      @Param("targetId") Long targetId,
                                      @Param("minutes") Integer minutes);

    /**
     * 查询聚合通知分组信息
     * @param userId 用户ID
     * @param query 查询条件
     * @return 聚合分组信息列表
     */
    List<Map<String, Object>> selectNotificationGroups(@Param("userId") Long userId,
                                                        @Param("query") NotificationQueryRequest query);

    /**
     * 查询指定分组的通知ID列表
     * @param userId 用户ID
     * @param type 通知类型
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @return 通知ID列表
     */
    List<Long> selectNotificationIdsByGroup(@Param("userId") Long userId,
                                             @Param("type") String type,
                                             @Param("targetType") String targetType,
                                             @Param("targetId") Long targetId);

    /**
     * 查询指定分组的发送者列表（最多3个）
     * @param userId 用户ID
     * @param type 通知类型
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @param limit 限制数量
     * @return 发送者信息列表
     */
    List<Map<String, Object>> selectSendersByGroup(@Param("userId") Long userId,
                                                    @Param("type") String type,
                                                    @Param("targetType") String targetType,
                                                    @Param("targetId") Long targetId,
                                                    @Param("limit") Integer limit);

    /**
     * 批量查询多个分组的发送者信息（优化N+1查询）
     * @param userId 用户ID
     * @param groupKeys 分组Key列表 (格式: type_targetType_targetId)
     * @return 发送者信息列表（包含groupKey字段）
     */
    List<Map<String, Object>> selectSendersByGroups(@Param("userId") Long userId,
                                                     @Param("groupKeys") List<String> groupKeys);

    /**
     * 分页查询聚合通知列表
     * @param page 分页对象
     * @param userId 用户ID
     * @param query 查询条件
     * @return 聚合通知分页列表
     */
    IPage<NotificationGroupResponse> selectGroupedNotificationPage(Page<NotificationGroupResponse> page,
                                                                    @Param("userId") Long userId,
                                                                    @Param("query") NotificationQueryRequest query);

    /**
     * 查找聚合点赞通知（用于更新）
     * @param userId 接收者用户ID
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @return 聚合通知（如果存在）
     */
    Notification findAggregatedLikeNotification(@Param("userId") Long userId,
                                                 @Param("targetType") String targetType,
                                                 @Param("targetId") Long targetId);

    /**
     * 更新聚合点赞通知
     * @param notificationId 通知ID
     * @param newSenderId 新的点赞者ID
     * @param senderIds 更新后的发送者ID列表（JSON）
     * @param senderCount 更新后的发送者数量
     * @return 影响行数
     */
    int updateAggregatedLikeNotification(@Param("notificationId") Long notificationId,
                                         @Param("newSenderId") Long newSenderId,
                                         @Param("senderIds") String senderIds,
                                         @Param("senderCount") Integer senderCount);

    /**
     * 批量查询文章信息（用于填充通知的目标信息）
     * @param articleIds 文章ID列表
     * @return 文章信息Map，key为文章ID
     */
    List<Map<String, Object>> selectArticlesByIds(@Param("articleIds") List<Long> articleIds);

    /**
     * 批量查询评论信息（用于填充通知的目标信息）
     * @param commentIds 评论ID列表
     * @param userId 当前用户ID（用于查询点赞状态）
     * @return 评论信息Map，key为评论ID
     */
    List<Map<String, Object>> selectCommentsByIds(@Param("commentIds") List<Long> commentIds,
                                                   @Param("userId") Long userId);

    /**
     * 批量查询用户信息（用于填充通知的发送者/目标信息）
     * @param userIds 用户ID列表
     * @return 用户信息Map，key为用户ID
     */
    List<Map<String, Object>> selectUsersByIds(@Param("userIds") List<Long> userIds);

    /**
     * 查询指定分组的详细通知列表（用于展开查看）
     * @param userId 用户ID
     * @param type 通知类型
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @return 通知详情列表
     */
    List<NotificationResponse> selectGroupDetailNotifications(@Param("userId") Long userId,
                                                               @Param("type") String type,
                                                               @Param("targetType") String targetType,
                                                               @Param("targetId") Long targetId);

    /**
     * 删除指定天数前的已读通知
     * @param days 天数
     * @return 删除的记录数
     */
    int deleteOldReadNotifications(@Param("days") int days);

    /**
     * 删除超过指定数量的通知（每个分组保留最新的N条）
     * @param type 通知类型
     * @param keepCount 保留数量
     * @return 删除的记录数
     */
    int deleteExcessNotifications(@Param("type") String type, @Param("keepCount") int keepCount);
}

